#include "DataManager.h"

#include "EventCollection.h"
#include "EventFileDriver.h"
#include "EventNode.h"
#include "EventObject.h"
#include "EventString.h"
#include "EventTable.h"
#include "GroupTable.h"
#include "KeepTable.h"
#include "UserTable.h"

#include <libintl.h>
#include <stdio.h>
#include <stdlib.h>
#define _(String)	     gettext(String)
#define gettext_noop(String) String

const char *event_file_driver_failed[EVENT_FILE_DRIVER_END] = {
	gettext_noop("Success and no error.\n"),
	gettext_noop("NULL Object error!\n"),
	gettext_noop("Parser function was not set in Object.\n"),
	gettext_noop("Loader path was not set.\n"),
	gettext_noop(
		"EFD file has been opened and repeated loading is rejected.\n"),
	gettext_noop("EFD file open error. (System I/O is correct? )\n"),
	gettext_noop("EFD magic check failed in file.\n"),
	gettext_noop("EFD file is imcomplete.\n"),
	gettext_noop("EFD file size check failed.\n"),
	gettext_noop("Item number check failed.\n"),
	gettext_noop("Occur error when parser data.\n"),
	gettext_noop("Occur error when generate data pack.\n"),
	gettext_noop("Data table not loaded.\n"),
	gettext_noop("EFD file read error.\n"),
	gettext_noop("Occur error when prepare data.\n"),
};

struct _DataManager
{
	EventObject parent_instance;

	KeepTable  *k_table;
	UserTable  *u_table;
	GroupTable *g_table;
	/* 事件表集合 */
	EventCollection *e_collection;

	/* 数据管理层的基础目录 */
	EventString *base_path;

	/* 事件表目录 */
	EventString *event_path;

	/* 当前操作的结果 */
	DataManagerRet result;

	/* 各数据表是否已准备好？*/
	bool is_inited;
};

static void
data_manager_finalize(DataManager *self)
{
	/* 写入数据防止丢失 */
	event_file_driver_dump(EVENT_FILE_DRIVER(self->g_table));
	event_file_driver_dump(EVENT_FILE_DRIVER(self->k_table));
	event_file_driver_dump(EVENT_FILE_DRIVER(self->u_table));
	/* 解引用事件条目表集合，内置析构会自动写入数据 */
	event_object_unref(self->e_collection);
	/* 再解引用数据 */
	event_object_unref(self->g_table);
	event_object_unref(self->k_table);
	event_object_unref(self->u_table);
	event_object_unref(self->base_path);
	event_object_unref(self->event_path);
	event_debug(DataManager, data_manager_finalize, "数据已保存。");
}

DataManager *
data_manager_new(void)
{
	DataManager *object = MALLOC_NEW(DataManager);

	event_object_init(EVENT_OBJECT(object));
	event_object_set_finalize(object, FINALIZE(data_manager_finalize));

	object->k_table	     = keep_table_new();
	object->g_table	     = group_table_new();
	object->u_table	     = user_table_new();
	object->e_collection = event_collection_new();
	object->base_path    = NULL;
	object->event_path   = NULL;
	object->is_inited    = false;
	object->result	     = DATA_MANAGER_SUCCESS;

	return object;
}

void
data_manager_set_base_path(DataManager *self, const char *base_path)
{
	EventString *path;
	return_if_fail(self != NULL && base_path != NULL,
		       data_manager_set_base_path);

	if (self->base_path) {
		printf(_("The directory has been set as '%s', and repeated "
			 "directory setting is rejected!\n"),
		       ES_GET(self->base_path));
		return;
	}

	self->base_path = event_string_new(base_path);
	event_string_append(self->base_path, "/");

	self->event_path = event_string_new(base_path);
	event_string_append(self->event_path, "/event/");
	event_collection_set_path(self->e_collection, self->event_path);

	path = event_string_copy_append(self->base_path, "keep.efd");
	event_file_driver_set_file(EVENT_FILE_DRIVER(self->k_table),
				   ES_GET(path));
	event_object_unref(path);

	path = event_string_copy_append(self->base_path, "group.efd");
	event_file_driver_set_file(EVENT_FILE_DRIVER(self->g_table),
				   ES_GET(path));
	event_object_unref(path);

	path = event_string_copy_append(self->base_path, "user.efd");
	event_file_driver_set_file(EVENT_FILE_DRIVER(self->u_table),
				   ES_GET(path));
	event_object_unref(path);
}

/* 若无文件则在 EventFileDriver 层面直接创建新文件 */
static void
data_manager_init_all(DataManager *self)
{
	int status, errors = 0;
	return_if_fail(self != NULL, data_manager_init_all);
	if (self->is_inited)
		return;
	status = event_file_driver_loader(EVENT_FILE_DRIVER(self->k_table));
	if (status != EVENT_FILE_DRIVER_SUCCESS &&
	    status != EVENT_FILE_DRIVER_TABLE_LOADED_ERROR) {
		printf("%s", EFD_FAILED(status));
		errors += 1;
	}
	status = event_file_driver_loader(EVENT_FILE_DRIVER(self->g_table));
	if (status != EVENT_FILE_DRIVER_SUCCESS &&
	    status != EVENT_FILE_DRIVER_TABLE_LOADED_ERROR) {
		printf("%s", EFD_FAILED(status));
		errors += 1;
	}
	status = event_file_driver_loader(EVENT_FILE_DRIVER(self->u_table));
	if (status != EVENT_FILE_DRIVER_SUCCESS &&
	    status != EVENT_FILE_DRIVER_TABLE_LOADED_ERROR) {
		printf("%s", EFD_FAILED(status));
		errors += 1;
	}

	if (errors != 0) {
		printf(_("Error number: %d, when init data table.\n"), errors);
		return;
	}
	self->is_inited = true;
	/* 确保系统默认事件组存在 */
	group_table_make_sure_default_exist(self->g_table);
}

int
data_manager_init(DataManager *self)
{
	return_val_if_fail(self != NULL, data_manager_init,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	data_manager_init_all(self);
	if (!self->is_inited)
		return DATA_MANAGER_NOT_INITIALIZE_ERROR;
	else
		return DATA_MANAGER_SUCCESS;
}

euint32
data_manager_get_uid_from_oid(DataManager *self, euint64 online_id)
{
	return_val_if_fail(self != NULL, data_manager_get_uid_from_oid, 0);
	data_manager_init_all(self);
	if (!self->is_inited) {
		printf(_("There is a data table loading error!\n"));
		return 0;
	}
	return keep_table_get_uid_from_oid(self->k_table, online_id);
}

euint32
data_manager_get_uid_from_phone(DataManager *self, euint64 phone)
{
	return_val_if_fail(self != NULL, data_manager_get_uid_from_phone, 0);
	return user_table_get_uid_from_phone(self->u_table, phone);
}

euint64
data_manager_get_phone_from_uid(DataManager *self, euint32 user_id)
{
	return_val_if_fail(self != NULL, data_manager_get_phone_from_uid, 0);
	return user_table_get_phone_from_uid(self->u_table, user_id);
}

int
data_manager_register(DataManager *self, euint64 phone, EventString *user_name,
		      EventString *password)
{
	euint32 uid;
	return_val_if_fail(self != NULL, data_manager_register,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	data_manager_init_all(self);
	if (!self->is_inited)
		return DATA_MANAGER_NOT_INITIALIZE_ERROR;
	uid = user_table_get_uid_from_phone(self->u_table, phone);
	if (uid != 0)
		return DATA_MANAGER_USER_ALREADY_EXISTS_ERROR;

	uid = user_table_add_initialize_user(self->u_table, phone, user_name,
					     password);
	if (uid == 0)
		return DATA_MANAGER_NULL_OBJECT_ERROR;
	/* 将用户添加到系统默认事件组 'System Group' */
	group_table_add_member(self->g_table, 1, uid, false);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_verify_user(DataManager *self, euint64 phone,
			 const EventString *password)
{
	return_val_if_fail(self != NULL && password != NULL,
			   data_manager_verify_user,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	UserItem *item = user_table_get_uitem_from_phone(self->u_table, phone);
	if (!item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	if (user_item_compare_password(item, password))
		return DATA_MANAGER_SUCCESS;
	else
		return DATA_MANAGER_USER_VERIFY_FAILED;
}

int
data_manager_verify_logon_state(DataManager *self, euint64 oid)
{
	return_val_if_fail(self != NULL, data_manager_verify_logon_state, 2);
	return keep_table_verify_logon_state(self->k_table, oid);
}

int
data_manager_flush_online_state(DataManager *self, euint64 online_id)
{
	return_val_if_fail(self != NULL, data_manager_flush_online_state,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	return keep_table_flush_online_state(self->k_table, online_id, false);
}

euint64
data_manager_add_keep_item(DataManager *self, euint32 user_id)
{
	time_t	now_time;
	euint64 online_id;
	return_val_if_fail(self != NULL, data_manager_add_keep_item, 0L);

	now_time  = time(NULL);
	online_id = now_time + user_id;
	do {
		online_id += (user_id + now_time % user_id);
		if (online_id > __INT64_MAX__)
			online_id = online_id - __INT64_MAX__ + user_id + 1;
	} while (keep_table_verify_existed_online_id(self->k_table, online_id));
	keep_table_add_online_item(self->k_table, online_id, user_id);
	return online_id;
}

int
data_manager_modify_user_password(DataManager *self, euint32 user_id,
				  EventString *modify_password)
{
	UserItem *u_item;
	return_val_if_fail(self != NULL || modify_password != NULL,
			   data_manager_modify_user_password,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	user_item_set_password(u_item, modify_password);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_user_name(DataManager *self, euint32 user_id,
			      EventString *modify_user_name)
{
	UserItem *u_item;
	return_val_if_fail(self != NULL || modify_user_name != NULL,
			   data_manager_modify_user_name,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	user_item_set_user_name(u_item, modify_user_name);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_group_name(DataManager *self, euint32 operator_uid,
			       euint32 group_id, EventString *group_name)
{
	GroupItem *g_item;
	return_val_if_fail(self != NULL || group_name != NULL,
			   data_manager_modify_group_name,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_uid)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	group_item_set_group_name(g_item, group_name);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_event_item(DataManager *self, euint32 creator_uid,
			       euint32 group_id, euint32 event_id,
			       time_t end_time, EventString *event_name,
			       EventString *event_describe, bool is_important)
{
	EventTable *e_table;
	GroupItem  *g_item;
	euint32	    re_eid;
	return_val_if_fail(
		self != NULL && event_name != NULL && event_describe != NULL,
		data_manager_modify_event_item, DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (!g_item->g_can_write)
		return DATA_MANAGER_GROUP_GLOBAL_CAN_NOT_WRITE;
	if (!group_item_verify_write_flag(g_item, creator_uid))
		return DATA_MANAGER_GROUP_CAN_NOT_WRITE;
	e_table = event_collection_load_table(self->e_collection, group_id,
					      false);
	if (!e_table)
		return DATA_MANAGER_EVENT_TABLE_NOT_EXIST_ERROR;
	re_eid = event_table_set_event(e_table, event_id, creator_uid, end_time,
				       event_name, event_describe,
				       is_important);
	if (re_eid == 0)
		return DATA_MANAGER_EVENT_ITEM_NOT_EXIST_ERROR;
	else
		return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_group_can_write_flag(DataManager *self, euint32 operator_id,
					 euint32 group_id, bool can_write)
{
	GroupItem *g_item;
	return_val_if_fail(self != NULL,
			   data_manager_modify_group_can_write_flag,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_id)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	g_item->g_can_write = can_write;
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_member_can_write_flag(DataManager *self,
					  euint32 operator_id, euint32 group_id,
					  euint32 modify_uid, bool can_write)
{
	GroupItem *g_item;
	return_val_if_fail(self != NULL,
			   data_manager_modify_member_can_write_flag,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_id)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	group_item_set_member(g_item, modify_uid, can_write);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_modify_group_can_join_flag(DataManager *self, euint32 operator_id,
					euint32 group_id, bool can_join)
{
	GroupItem *g_item;
	return_val_if_fail(self != NULL,
			   data_manager_modify_group_can_join_flag,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (g_item->user_id != operator_id)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	g_item->can_join = can_join;
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_create_group(DataManager *self, euint32 operator_uid,
			  EventString *group_name, bool g_can_write,
			  bool can_join)
{
	UserItem *u_item;
	euint32	  group_id;
	return_val_if_fail(self != NULL, data_manager_create_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	group_id = group_table_add_item(self->g_table, operator_uid, group_name,
					g_can_write, can_join);
	if (group_id == 0)
		return DATA_MANAGER_NULL_OBJECT_ERROR;
	u_item = user_table_get_uitem_from_uid(self->u_table, operator_uid);
	if (!u_item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	user_item_add_group_id(u_item, group_id);
	return (int)group_id;
}

int
data_manager_create_event(DataManager *self, euint32 operator_uid,
			  euint32 group_id, time_t end_time,
			  EventString *event_name, EventString *event_describe,
			  bool is_important)
{
	EventTable *e_table;
	GroupItem  *g_item;
	return_val_if_fail(self != NULL, data_manager_create_event,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (!g_item->g_can_write)
		return DATA_MANAGER_GROUP_GLOBAL_CAN_NOT_WRITE;
	if (!group_item_verify_write_flag(g_item, operator_uid))
		return DATA_MANAGER_GROUP_CAN_NOT_WRITE;
	e_table =
		event_collection_load_table(self->e_collection, group_id, true);
	return (int)event_table_set_event(e_table, 0, operator_uid, end_time,
					  event_name, event_describe,
					  is_important);
}

int
data_manager_add_user_to_group(DataManager *self, euint32 operator_uid,
			       euint32 addtion_uid, euint32 group_id)
{
	GroupItem *g_item;
	return_val_if_fail(self != NULL, data_manager_add_user_to_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_uid)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	if (!user_table_verify_user_exist(self->u_table, addtion_uid))
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	group_table_add_member(self->g_table, group_id, addtion_uid, false);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_flush_keep_state(DataManager *self, euint64 online_id)
{
	int status;
	return_val_if_fail(self != NULL, data_manager_flush_keep_state,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	status = keep_table_flush_online_state(self->k_table, online_id, true);
	if (status == 0)
		return DATA_MANAGER_SUCCESS;
	else if (status == 2)
		return DATA_MANAGER_NULL_OBJECT_ERROR;
	else
		return DATA_MANAGER_USER_NOT_LOGON;
}

int
data_manager_remove_group(DataManager *self, euint32 operator_uid,
			  euint32 will_remove_gid)
{
	GroupItem *g_item;
	UserItem  *u_item;
	GMember	  *g_member;
	return_val_if_fail(self != NULL, data_manager_remove_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	g_item = group_table_get_g_item(self->g_table, will_remove_gid);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_uid)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	group_item_iter_member_reset(g_item);
	g_member = group_item_iter_get_with_member(g_item);
	while (g_member) {
		u_item = user_table_get_uitem_from_uid(self->u_table,
						       g_member->user_id);
		if (u_item)
			user_item_remove_group_id(u_item, will_remove_gid);
		g_member = group_item_iter_get_with_member(g_item);
	}
	group_table_remove_group(self->g_table, will_remove_gid);
	event_collection_remove_table(self->e_collection, will_remove_gid);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_remove_member_from_group(DataManager *self, euint32 operator_uid,
				      euint32 group_id, euint32 will_remove_uid)
{
	GroupItem *g_item;
	UserItem  *u_item;
	int	   status;
	return_val_if_fail(self != NULL, data_manager_remove_member_from_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->user_id != operator_uid)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	status = group_item_remove_member(g_item, will_remove_uid);
	if (status == 1)
		return DATA_MANAGER_USER_NOT_BELONG_GROUP;
	u_item = user_table_get_uitem_from_uid(self->u_table, will_remove_uid);
	if (u_item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	user_item_remove_group_id(u_item, group_id);
	return DATA_MANAGER_SUCCESS;
}

int
data_manager_remove_event_from_group(DataManager *self, euint32 operator_uid,
				     euint32 group_id, euint32 will_remove_eid)
{
	GroupItem  *g_item;
	EventTable *e_table;
	int	    status;
	return_val_if_fail(self != NULL, data_manager_remove_event_from_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (!group_item_verify_write_flag(g_item, operator_uid))
		return DATA_MANAGER_GROUP_CAN_NOT_WRITE;
	e_table =
		event_collection_load_table(self->e_collection, group_id, true);
	status = event_table_remove_event(e_table, will_remove_eid);
	if (status == 2)
		return DATA_MANAGER_EVENT_ITEM_NOT_EXIST_ERROR;
	else if (status == 1)
		return DATA_MANAGER_NULL_OBJECT_ERROR;
	else
		return DATA_MANAGER_SUCCESS;
}

int
data_manager_handle_user_quit_from_group(DataManager *self, euint32 user_id,
					 euint32 group_id)
{
	GroupItem *g_item;
	UserItem  *u_item;
	int	   status;
	return_val_if_fail(self != NULL,
			   data_manager_handle_user_quit_from_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (g_item->group_id == 1)
		return DATA_MANAGER_CAN_NOT_QUIT_DEFAULT_GROUP;
	status = group_item_remove_member(g_item, user_id);
	if (status == 1)
		return DATA_MANAGER_USER_NOT_BELONG_GROUP;
	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return DATA_MANAGER_USER_NOT_REGISTER_ERROR;
	user_item_remove_group_id(u_item, group_id);
	return DATA_MANAGER_SUCCESS;
}

EventList *
data_manager_user_fetch_all_event(DataManager *self, euint32 user_id)
{
	EventList	*response_list, *response_node;
	const EventList *group_node;
	EventTable	*e_table;
	UserItem	*u_item;
	EventItem	*e_item;
	GroupItem	*g_item;
	EventString	*group_name;
	euint32		 group_id;
	bool		 user_can_write;
	return_val_if_fail(self != NULL, data_manager_user_fetch_all_event,
			   NULL);
	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return NULL;
	group_node = user_item_get_group_list(u_item);
	if (!group_node)
		return NULL;
	response_list = event_list_new();
fetch_next_item:
	if (!event_list_verify_node_type(group_node, EVENT_TYPE_UINT32))
		return response_list;
	group_id = (euint32)EN_GET_D(group_node, euint64);
	e_table	 = event_collection_load_table(self->e_collection, group_id,
					       false);
	if (!e_table)
		goto get_next_node;
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		goto get_next_node;
	user_can_write = group_item_verify_write_flag(g_item, user_id);
	event_table_iter_reset(e_table);
iteration_once:
	e_item = event_table_iter_get(e_table);
	if (!e_item)
		goto get_next_node;
	response_node = event_list_new();
	event_list_add_data(response_node, EPTR((euint64)group_id),
			    EVENT_TYPE_UINT32, NULL);
	group_name = group_item_dup_group_name(g_item);
	event_list_add_data(response_node, group_name, EVENT_TYPE_STRING,
			    event_object_unref);
	event_list_add_data(response_node, EPTR((euint64)e_item->event_id),
			    EVENT_TYPE_UINT32, NULL);
	event_list_add_data(response_node, EPTR(e_item->end_time),
			    EVENT_TYPE_INT64, NULL);
	event_list_add_data(response_node, EO_REF(e_item->event_name, epointer),
			    EVENT_TYPE_STRING, event_object_unref);
	event_list_add_data(response_node,
			    EO_REF(e_item->event_describe, epointer),
			    EVENT_TYPE_STRING, event_object_unref);
	event_list_add_data(response_node, EPTR((euint64)user_can_write),
			    EVENT_TYPE_UINT8, NULL);
	event_list_add_data(response_node, EPTR((euint64)e_item->is_important),
			    EVENT_TYPE_UINT8, NULL);
	/* 将 EventList 单节点添加到返回链中 */
	event_list_add_data(response_list, response_node, EVENT_TYPE_LIST,
			    event_object_unref);
	goto iteration_once;
get_next_node:
	group_node = EN_GET_NEXT(group_node, EventList *);
	if (!group_node)
		return response_list;
	else
		goto fetch_next_item;
}

EventList *
data_manager_user_fetch_all_group_info(DataManager *self, euint32 user_id)
{
	EventList	*response_list, *response_node;
	const EventList *group_node;
	UserItem	*u_item;
	GroupItem	*g_item;
	EventString	*group_name;
	euint32		 group_id;
	bool		 is_creator, can_write;
	return_val_if_fail(self != NULL, data_manager_user_fetch_all_group_info,
			   NULL);
	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return NULL;
	group_node = user_item_get_group_list(u_item);
	if (!group_node)
		return NULL;
	response_list = event_list_new();
fetch_next_item:
	if (!event_list_verify_node_type(group_node, EVENT_TYPE_UINT32))
		return response_list;
	group_id = (euint32)EN_GET_D(group_node, euint64);
	g_item	 = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		goto get_next_node;
	is_creator    = (g_item->user_id == user_id);
	can_write     = group_item_verify_write_flag(g_item, user_id);
	group_name    = group_item_dup_group_name(g_item);
	response_node = event_list_new();
	event_list_add_data(response_node, EPTR((euint64)group_id),
			    EVENT_TYPE_UINT32, NULL);
	event_list_add_data(response_node, group_name, EVENT_TYPE_STRING,
			    event_object_unref);
	event_list_add_data(response_node, EPTR((euint64)is_creator),
			    EVENT_TYPE_UINT8, NULL);
	event_list_add_data(response_node, EPTR((euint64)can_write),
			    EVENT_TYPE_UINT8, NULL);
	event_list_add_data(response_node, EPTR((euint64)g_item->can_join),
			    EVENT_TYPE_UINT8, NULL);
	event_list_add_data(response_node, EPTR((euint64)g_item->g_can_write),
			    EVENT_TYPE_UINT8, NULL);
	/* 将 EventList 单节点添加到返回链中 */
	event_list_add_data(response_list, response_node, EVENT_TYPE_LIST,
			    event_object_unref);
get_next_node:
	group_node = EN_GET_NEXT(group_node, EventList *);
	if (!group_node)
		return response_list;
	else
		goto fetch_next_item;
}

static EventString *__dup_joined_group_name = NULL;

int
data_manager_user_join_group(DataManager *self, euint32 operator_uid,
			     euint32 group_id)
{
	GroupItem *g_item;
	__dup_joined_group_name = NULL;
	return_val_if_fail(self != NULL, data_manager_user_join_group,
			   DATA_MANAGER_NULL_OBJECT_ERROR);

	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item)
		return DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
	if (!g_item->can_join)
		return DATA_MANAGER_GROUP_PERMISSION_DENIED;
	if (group_item_verify_user_existed(g_item, operator_uid))
		return DATA_MANAGER_USER_EXISTED_IN_GROUP;
	group_item_set_member(g_item, operator_uid, false);
	user_table_add_group_item(self->u_table, operator_uid, group_id);
	__dup_joined_group_name =
		event_string_new(ES_GET(group_item_get_group_name(g_item)));
	return DATA_MANAGER_SUCCESS;
}

EventString *
data_manager_dup_user_joined_group_name(DataManager *self)
{
	return __dup_joined_group_name;
}

EventString *
data_manager_dup_user_name(DataManager *self, euint32 user_id)
{
	UserItem *u_item;
	return_val_if_fail(self != NULL, data_manager_dup_user_name, NULL);
	u_item = user_table_get_uitem_from_uid(self->u_table, user_id);
	if (!u_item)
		return NULL;
	return user_item_dup_user_name(u_item);
}

EventList *
data_manager_fetch_all_memeber_info(DataManager *self, euint32 operator_uid,
				    euint32 group_id)
{
	GroupItem   *g_item;
	UserItem    *u_item;
	EventList   *response_list, *response_node;
	GMember	    *gmember;
	EventString *user_name;

	self->result = DATA_MANAGER_NULL_OBJECT_ERROR;
	return_val_if_fail(self != NULL, data_manager_fetch_all_memeber_info,
			   NULL);
	g_item = group_table_get_g_item(self->g_table, group_id);
	if (!g_item) {
		self->result = DATA_MANAGER_GROUP_NOT_EXIST_ERROR;
		return NULL;
	}
	if (g_item->user_id != operator_uid) {
		self->result = DATA_MANAGER_GROUP_PERMISSION_DENIED;
		return NULL;
	}
	group_item_iter_member_reset(g_item);
	response_list = event_list_new();

re_iteration:
	gmember = group_item_iter_get_with_member(g_item);
	if (!gmember) {
		self->result = DATA_MANAGER_SUCCESS;
		return response_list;
	}
	u_item = user_table_get_uitem_from_uid(self->u_table, gmember->user_id);
	response_node = event_list_new();
	event_list_add_data(response_node, EPTR((euint64)group_id),
			    EVENT_TYPE_UINT32, NULL);
	event_list_add_data(response_node, EPTR((euint64)gmember->user_id),
			    EVENT_TYPE_UINT32, NULL);
	event_list_add_data(response_node, EPTR((euint64)gmember->can_write),
			    EVENT_TYPE_UINT8, NULL);
	if (u_item) {
		user_name = user_item_dup_user_name(u_item);
		event_list_add_data(response_node, user_name, EVENT_TYPE_STRING,
				    event_object_unref);
	}
	//
	event_list_add_data(response_list, response_node, EVENT_TYPE_LIST,
			    event_object_unref);
	goto re_iteration;
}

DataManagerRet
data_manager_get_result(DataManager *self)
{
	return self->result;
}
